home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 June / EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso / earcd / c-lang / vbcc.lha / vbcc / flow.c < prev    next >
C/C++ Source or Header  |  1996-05-15  |  21KB  |  507 lines

  1. /*  $VER: vbcc (flow.c) V0.3     */
  2. /*  Generierung des FLussgraphs und Optimierungen des Kontrollflusses   */
  3.  
  4. #include "opt.h"
  5.  
  6. int bvcmp(unsigned char *dest,unsigned char *src,size_t len)
  7. /*  vergleicht zwei Bitvektoren    */
  8. {
  9.     for(;len>0;len--)
  10.         if(*dest++!=*src++) return(0);
  11.     return(1);
  12. }
  13. void bvunite(unsigned char *dest,unsigned char *src,size_t len)
  14. /*  berechnet Vereinigung zweier Bitvektoren    */
  15. {
  16.     for(;len>0;len--)
  17.         *dest++|=*src++;
  18. }
  19. void bvintersect(unsigned char *dest,unsigned char *src,size_t len)
  20. /*  berechnet Durchschnitt zweier Bitvektoren   */
  21. {
  22.     for(;len>0;len--)
  23.         *dest++&=*src++;
  24. }
  25. void bvdiff(unsigned char *dest,unsigned char *src,size_t len)
  26. /*  berechnet 'Differenz' zweier Bitvektoren    */
  27. {
  28.     for(;len>0;len--)
  29.         *dest++&=~(*src++);
  30. }
  31.  
  32. unsigned int basic_blocks;
  33.  
  34. struct flowgraph *construct_flowgraph(void)
  35. /*  entfernt ueberfluessige Labels und erzeugt Flussgraph   */
  36. {
  37.     struct IC *p;
  38.     int firstl=lastlabel,lcnt=label-firstl,currentl,i,code,l;
  39.     int *iseq=mymalloc(lcnt*sizeof(int));
  40.     int *used=mymalloc(lcnt*sizeof(int));
  41.     struct flowgraph **lg=mymalloc(lcnt*sizeof(struct flowgraph *));
  42.     struct flowgraph *g=mymalloc(sizeof(struct flowgraph)),*fg=g;
  43.     g->start=first_ic;g->in=0;g->branchout=0;g->loopend=0;
  44.  
  45.     for(i=0;i<lcnt;i++) {iseq[i]=used[i]=0;lg[i]=0;}
  46.     currentl=0;firstl++;
  47.     /*  Diese Schleife entfernt alle Labels, die mit anderen    */
  48.     /*  uebereinstimmen, merkt sich das und kennzeichnet alle   */
  49.     /*  Labels, die benutzt werden.                             */
  50.     /*  Ausserdem wird der Flussgraph teilweise aufgebaut.      */
  51.     if(DEBUG&1024) {puts("construct_flowgraph(): loop1");/*scanf("%d",&i);*/}
  52.     i=1;g->index=i;
  53.     for(p=first_ic;p;p=p->next){
  54.         code=p->code;
  55.         if(code>=BEQ&&code<=BRA){
  56.             l=p->typf;
  57.             /*  als used markieren; falls aequivalent, das erste markieren  */
  58.             if(iseq[l-firstl]) used[iseq[l-firstl]-firstl]=1;
  59.                 else           used[l-firstl]=1;
  60.             /*  Flussgraph beenden und evtl. naechsten Knoten erzeugen  */
  61.             g->end=p;
  62.             if(p->next){
  63.                 g->normalout=mymalloc(sizeof(struct flowgraph));
  64.                 g->normalout->in=mymalloc(sizeof(struct flowlist));
  65.                 g->normalout->in->next=0;
  66.                 g->normalout->in->graph=g;
  67.                 g=g->normalout;
  68.                 g->start=p->next;
  69.                 g->branchout=0;
  70.                 g->loopend=0;
  71.                 g->index=++i;
  72.             }else g->normalout=0;
  73.  
  74.             currentl=0;continue;
  75.         }
  76.         if(code==ALLOCREG||code==FREEREG) continue;
  77.         if(code!=LABEL){currentl=0;continue;}
  78.         /*  ist ein Label   */
  79.         l=p->typf;
  80.         if(currentl){
  81.             iseq[l-firstl]=currentl;
  82.             if(used[l-firstl]) used[currentl-firstl]=1;
  83.             remove_IC(p);
  84. /*            if(DEBUG&1024) printf("label %d==%d\n",l,iseq[l-firstl]);*/
  85.         }else{
  86.             currentl=l;
  87.             if(g->start!=p){
  88.                 g->end=p->prev;
  89.                 g->normalout=mymalloc(sizeof(struct flowgraph));
  90.                 g->normalout->in=mymalloc(sizeof(struct flowlist));
  91.                 g->normalout->in->next=0;
  92.                 g->normalout->in->graph=g;
  93.                 g=g->normalout;
  94.                 g->start=p;
  95.                 g->branchout=0;
  96.                 g->loopend=0;
  97.                 g->index=++i;
  98.             }else g->branchout=0;
  99.             lg[l-firstl]=g;
  100.         }
  101.     }
  102.     g->end=last_ic;g->normalout=g->branchout=0;
  103.     if(DEBUG&1024) printf("%d basic blocks\n",i);
  104.     basic_blocks=i;
  105.  
  106. /*    if(DEBUG&1024) for(i=firstl;i<=lcnt;i++) printf("L%d used: %d\n",i,used[i-firstl]);*/
  107.     /*  Diese Schleife entfernt alle nicht benutzten Labels und biegt alle  */
  108.     /*  Branches auf aequivalente Labels um.                                */
  109.     if(DEBUG&1024) {puts("construct_flowgraph(): loop2");/*scanf("%d",&i);*/}
  110.     g=fg;
  111.     while(g){
  112.         int flag=0;struct flowlist *lp;
  113. /*        printf("g=%p\n",(void *)g);*/
  114.         g->av_in=g->av_out=g->av_gen=g->av_kill=0;
  115.         g->rd_in=g->rd_out=g->rd_gen=g->rd_kill=0;
  116.         g->ae_in=g->ae_out=g->ae_gen=g->ae_kill=0;
  117.         g->cp_in=g->cp_out=g->cp_gen=g->cp_kill=0;
  118.         p=g->start;
  119.         while(p&&!flag){
  120. /*            pric2(stdout,p);*/
  121.             code=p->code;
  122.             if(code>=BEQ&&code<=BRA){
  123.                 l=p->typf;
  124.                 if(iseq[l-firstl]) p->typf=l=iseq[l-firstl];
  125.                 /*  in Flussgraph eintragen */
  126.                 g->branchout=lg[l-firstl];
  127.                 if(!lg[l-firstl]) ierror(0);
  128.                 lp=lg[l-firstl]->in;
  129.                 /*  das hier sollte man noch schoener machen    */
  130.                 if(!lp){
  131.                     lg[l-firstl]->in=mymalloc(sizeof(struct flowlist));
  132.                     lg[l-firstl]->in->next=0;
  133.                     lg[l-firstl]->in->graph=g;
  134.                 }else{
  135.                     while(lp&&lp->next) lp=lp->next;
  136.                     lp->next=mymalloc(sizeof(struct flowlist));
  137.                     lp->next->next=0;
  138.                     lp->next->graph=g;
  139.                 }
  140.             }
  141. /*            if(code==LABEL&&!used[p->typf-firstl]) remove_IC(p);*/
  142.             if(p==g->end) flag=1;
  143.             p=p->next;
  144.         }
  145.         g=g->normalout;
  146.     }
  147.     /*  Unbenutzte Labels entfernen und Bloecke verbinden   */
  148.     if(DEBUG&1024) {puts("construct_flowgraph(): loop3");/*scanf("%d",&i);*/}
  149.     for(g=fg;g;g=g->normalout){
  150.         if(g->end&&(g->end->code<BEQ||g->end->code>BRA)){
  151.             struct flowgraph *next=g->normalout;struct flowlist *lp;
  152.             if(next&&next->start&&next->start->code==LABEL&&!used[next->start->typf-firstl]){
  153.                 if(next->end!=next->start) g->end=next->end;
  154.                 g->normalout=next->normalout;
  155.                 g->branchout=next->branchout;
  156.                 free(next->in); /*  darf eigentlich nur einen Vorgaenger haben  */
  157.                 /*  in im Nachfolgeknoten auf den ersten der beiden setzen  */
  158.                 if(next->normalout&&next->normalout->in) next->normalout->in->graph=g;
  159.                 /*  in im Ziel von next->branchout auf den ersten setzen    */
  160.                 if(next->branchout){
  161.                     lp=next->branchout->in;
  162.                     while(1){
  163.                         if(lp->graph==next){ lp->graph=g;break;}
  164.                         lp=lp->next;if(!lp) ierror(0);
  165.                     }
  166.                 }
  167.                 if(DEBUG&1024){ printf("unused label deleted:\n");pric2(stdout,next->start);}
  168.                 remove_IC(next->start);
  169.                 free(next);
  170.             }
  171.         }
  172.         /*  unbenutzte Labels entfernen */
  173.         if(g->start&&g->start->code==LABEL&&!used[g->start->typf-firstl])
  174.             remove_IC_fg(g,g->start);
  175.     }
  176.     free(iseq);
  177.     free(used);
  178.     return(fg);
  179. }
  180.  
  181. void print_flowgraph(struct flowgraph *g)
  182. /*  Gibt Flussgraph auf Bildschirm aus  */
  183. {
  184.     static int dontprint=0;
  185.     int flag,i;struct flowlist *lp;struct IC *ip;
  186.     if(dontprint) return;
  187.     if(DEBUG&1024) {puts("print_flowgraph()");scanf("%d",&i);}
  188.     if(i<0){dontprint=1;return;}
  189.     if(!i) return;
  190.     while(g){
  191.         printf("\nBasic Block nr. %d\n",g->index);
  192.         printf("\tin from ");
  193.         lp=g->in;
  194.         while(lp){if(lp->graph) printf("%d ",lp->graph->index);lp=lp->next;}
  195.         printf("\n\tout to %d %d\n",g->normalout?g->normalout->index:0,g->branchout?g->branchout->index:0);
  196.         if(g->loopend) printf("head of a loop ending at block %d\n",g->loopend->index);
  197.         if(i&2){
  198.             printf("av_gen:\n"); print_av(g->av_gen);
  199.             printf("av_kill:\n"); print_av(g->av_kill);
  200.             printf("av_in:\n"); print_av(g->av_in);
  201.             printf("av_out:\n"); print_av(g->av_out);
  202.         }
  203.         if(i&4){
  204.             printf("rd_gen:\n"); print_rd(g->rd_gen);
  205.             printf("rd_kill:\n"); print_rd(g->rd_kill);
  206.             printf("rd_in:\n"); print_rd(g->rd_in);
  207.             printf("rd_out:\n"); print_rd(g->rd_out);
  208.         }
  209.         if(i&8){
  210.             printf("ae_gen:\n"); print_ae(g->ae_gen);
  211.             printf("ae_kill:\n"); print_ae(g->ae_kill);
  212.             printf("ae_in:\n"); print_ae(g->ae_in);
  213.             printf("ae_out:\n"); print_ae(g->ae_out);
  214.         }
  215.         if(i&16){
  216.             printf("cp_gen:\n"); print_cp(g->cp_gen);
  217.             printf("cp_kill:\n"); print_cp(g->cp_kill);
  218.             printf("cp_in:\n"); print_cp(g->cp_in);
  219.             printf("cp_out:\n"); print_cp(g->cp_out);
  220.         }
  221.         if(i&32){
  222.             int r;
  223.             for(r=1;r<=MAXR;r++)
  224.                 if(g->regv[r]) printf("(%s),%d assigned to %s\n",g->regv[r]->identifier,g->regv[r]->offset,regnames[r]);
  225.         }
  226.         flag=0;ip=g->start;
  227.         while(ip&&!flag){
  228.             pric2(stdout,ip);
  229.             if(ip==g->end) flag=1;
  230.             ip=ip->next;
  231.         }
  232.         g=g->normalout;
  233.     }
  234. }
  235. void free_flowgraph(struct flowgraph *g)
  236. /*  Gibt Flussgraph frei    */
  237. {
  238.     struct flowgraph *pm;struct flowlist *lp,*lpm;
  239.     if(DEBUG&1024) puts("free_flowgraph()");
  240.     while(g){
  241.         lp=g->in;
  242.         while(lp){
  243.             lpm=lp->next;
  244.             free(lp);
  245.             lp=lpm;
  246.         }
  247.         free(g->av_in);
  248.         free(g->av_out);
  249.         free(g->av_gen);
  250.         free(g->av_kill);
  251.         free(g->rd_in);
  252.         free(g->rd_out);
  253.         free(g->rd_gen);
  254.         free(g->rd_kill);
  255.         free(g->ae_in);
  256.         free(g->ae_out);
  257.         free(g->ae_gen);
  258.         free(g->ae_kill);
  259.         free(g->cp_in);
  260.         free(g->cp_out);
  261.         free(g->cp_gen);
  262.         free(g->cp_kill);
  263.  
  264.         pm=g->normalout;
  265.         free(g);
  266.         g=pm;
  267.     }
  268. }
  269. struct flowgraph *jump_optimization(void)
  270. /*  entfernt ueberfluessige Spruenge etc.                           */
  271. {
  272.     struct flowgraph *fg,*g;struct IC *p;int changed,i;
  273.     struct flowlist *lp;
  274.     do{
  275.         changed=0;
  276.         fg=construct_flowgraph();
  277.         if(DEBUG&1024) {printf("jump_optimization() pass\n");print_flowgraph(fg);}
  278.         g=fg;
  279.         while(g){
  280.             /*  tote Bloecke entfernen                  */
  281.             if(g!=fg) i=0; else i=1;    /*  erster Block nie tot    */
  282.             lp=g->in;
  283.             while(lp){
  284.                 struct flowgraph *t=lp->graph;
  285.                 if(t){
  286.                     if((t!=g&&t->branchout==g)||!t->end||(t!=g&&t->end->code!=BRA)) i=1;
  287.                 }
  288.                 lp=lp->next;
  289.             }
  290.             if(!i){
  291.                 struct IC *m;
  292.                 if(DEBUG&1024) printf("deleting dead block %d\n",g->index);
  293.                 p=g->start;
  294.                 while(p&&!i){
  295.                     if(p==g->end) i=1;
  296.                     if(DEBUG&1024) pric2(stdout,p);
  297.                     m=p->next;
  298.                     remove_IC_fg(g,p);changed=gchanged=1;
  299.                     p=m;
  300.                 }
  301.                 if(g->branchout){
  302.                 /*  Eintrag in Ziel loeschen (nur einmal, falls auch normalout)    */
  303.                     lp=g->branchout->in;
  304.                     while(lp){
  305.                         if(lp->graph==g){ lp->graph=0;break;}
  306.                         lp=lp->next;
  307.                     }
  308.                     g->branchout=0;
  309.                 }
  310.                 g=g->normalout;continue;
  311.             }
  312.             /*  Spruenge zum folgenden Code entfernen   */
  313.             if(g->normalout&&g->normalout==g->branchout){
  314.                 p=g->end;
  315.                 if(!p||p->code<BEQ||p->code>BRA) ierror(0);
  316.                 if(DEBUG&1024){printf("branch to following label deleted:\n");pric2(stdout,p);}
  317.                 remove_IC_fg(g,p);g->branchout=0;changed=gchanged=1;
  318.                 p=g->end;
  319.                 /*  vorangehenden Vergleich auch entfernen  */
  320.                 if(p&&(p->code==COMPARE||p->code==TEST)){
  321.                     if(DEBUG&1024){printf("preceding comparison also deleted:\n");pric2(stdout,p);}
  322.                     remove_IC_fg(g,p);
  323.                 }
  324.             }
  325.             /*  Spruenge zu Spruengen umsetzen; einige Zeiger im Flussgraph */
  326.             /*  werden nicht korrekt aktualisiert, aber das sollte egal sein*/
  327.             p=g->start;
  328.             for(i=0;i<2;i++){
  329.                 if(i){if(p&&p->code==LABEL) p=p->next; else break;}
  330.                 if(p&&p->code>=BEQ&&p->code<=BRA){
  331.                     lp=g->in;
  332.                     while(lp){
  333.                         if(lp->graph&&lp->graph->branchout==g&&(lp->graph->end->code==p->code||p->code==BRA)&&lp->graph->end->typf!=p->typf){
  334.                             if(DEBUG&1024){printf("branch bypassed to L%d:\n",p->typf);pric2(stdout,lp->graph->end);}
  335.                             if(lp->graph->end->code<BEQ||lp->graph->end->code>BRA) ierror(0);
  336.                             lp->graph->branchout=g->branchout;
  337.                             lp->graph->end->typf=p->typf;changed=gchanged=1;
  338.                         }
  339.                         lp=lp->next;
  340.                     }
  341.                 }
  342.             }
  343.             /*  bcc l1;bra l2;l1 aendern    */
  344.             p=g->end;
  345.             if(p&&p->code>=BEQ&&p->code<BRA&&g->normalout){
  346.                 if(g->normalout->start&&g->normalout->start->code==BRA){
  347.                     if(g->normalout->normalout==g->branchout){
  348.                         g->branchout=g->normalout->branchout;
  349.                         i=p->typf;
  350.                         p->typf=g->normalout->start->typf;
  351.                         if(DEBUG&1024) printf("changing bcc l%d;bra l%d;l%d to b!cc l%d\n",i,p->typf,i,p->typf);
  352.                         switch(p->code){
  353.                         case BEQ: p->code=BNE;break;
  354.                         case BNE: p->code=BEQ;break;
  355.                         case BLT: p->code=BGE;break;
  356.                         case BGE: p->code=BLT;break;
  357.                         case BGT: p->code=BLE;break;
  358.                         case BLE: p->code=BGT;break;
  359.                         }
  360.                         g->normalout->branchout=g->normalout->normalout;
  361.                         g->normalout->start->typf=i;
  362.                         changed=gchanged=1;
  363.                     }
  364.                 }
  365.             }
  366.             /*  Haben alle Vorgaenger eines Blocks die selbe Anweisung am   */
  367.             /*  Blockende und keinen weiteren Nachfolger, dann kann die     */
  368.             /*  Anweisung in den Nachfogerblock geschoben werden            */
  369.             i=0;p=0;
  370.             for(lp=g->in;lp;lp=lp->next){
  371.                 if(lp->graph){
  372.                     struct IC *np;
  373.                     struct flowgraph *ng=lp->graph;
  374.                     struct flowlist *l2;
  375.                     /*  doppelte Bloecke loeschen und ueberspringen */
  376.                     for(l2=g->in;l2;l2=l2->next)
  377.                         if(l2!=lp&&l2->graph==ng) break;
  378.                     if(l2){ lp->graph=0;continue;}
  379.                     np=ng->end;
  380.                     if(!np){ i=-1;break;}
  381.                     if(ng->branchout&&np->code!=BRA){i=-1;break;}
  382.                     if(np->code==BRA) np=np->prev;
  383.                     if(!np){ i=-1;break;}
  384.                     if(!p){
  385.                         i=1;
  386.                         p=np;
  387.                     }else{
  388.                         if(p->code==np->code&&p->typf==np->typf&&
  389.                            p->code!=CALL&&p->code!=GETRETURN&&p->code!=PUSH&&
  390.                            !compare_objs(&p->q1,&np->q1,p->typf)&&
  391.                            !compare_objs(&p->q2,&np->q2,p->typf)&&
  392.                            !compare_objs(&p->z,&np->z,p->typf)){
  393.                             i++;
  394.                         }else{
  395.                             i=-1;
  396.                             break;
  397.                         }
  398.                     }
  399.                 }
  400.             }
  401.             if(i>1&&g->start){
  402.                 struct IC *new=mymalloc(ICS);
  403.                 if(DEBUG&1024){ printf("moving instruction from preceding blocks to successor:\n");pric2(stdout,p);}
  404.                 changed=gchanged=1;
  405.                 memcpy(new,p,ICS);
  406.                 if(g->start->code==LABEL){
  407.                     insert_IC_fg(g,g->start,new);
  408.                 }else{
  409.                     insert_IC_fg(g,g->start->prev,new);
  410.                 }
  411.                 for(lp=g->in;lp;lp=lp->next){
  412.                     struct flowgraph *ng=lp->graph;
  413.                     if(ng){
  414.                         if(!ng->end) ierror(0);
  415.                         if(ng->end->code==BRA){
  416.                             remove_IC_fg(ng,ng->end->prev);
  417.                         }else{
  418.                             remove_IC_fg(ng,ng->end);
  419.                         }
  420.                     }
  421.                 }
  422.             }
  423.             /*  Haben alle Nachfolger eines Blocks die selbe Anweisung am   */
  424.             /*  Blockbeginn und keinen weiteren Vorgaenger, dann kann die   */
  425.             /*  Anweisung in den Vorgaengerblock geschoben werden           */
  426.             if(g->branchout&&g->normalout&&g->branchout!=g->normalout&&g->end&&g->end->code!=BRA){
  427.                 struct flowgraph *a=g->normalout,*b=g->branchout;
  428.                 struct IC *as=a->start,*bs=b->start,*tp;
  429.                 int destroys;
  430.                 if(as&&as->code==LABEL&&as!=a->end) as=as->next;
  431.                 if(bs&&bs->code==LABEL&&bs!=b->end) bs=bs->next;
  432.  
  433.                 if(as&&bs&&as->code==bs->code&&as->code!=PUSH&&as->typf==bs->typf&&
  434.                    !compare_objs(&as->q1,&bs->q1,as->typf)&&
  435.                    !compare_objs(&as->q2,&bs->q2,as->typf)&&
  436.                    !compare_objs(&as->z,&bs->z,as->typf)){
  437.                     i=0;
  438.                     for(lp=a->in;lp;lp=lp->next)
  439.                         if(lp->graph&&lp->graph!=g&&(!lp->graph->end||lp->graph->end->code!=BRA)) i=1;
  440.                     for(lp=b->in;lp;lp=lp->next)
  441.                         if(lp->graph&&lp->graph!=g&&(!lp->graph->end||lp->graph->end->code!=BRA)) i=1;
  442.                     if(!i){
  443.                         if(!(tp=g->end->prev)) ierror(0);
  444.                         if(tp->code!=TEST&&tp->code!=COMPARE)
  445.                             ierror(0);
  446.                         /*  schauen, ob die Anweisung eine evtl. TEST   */
  447.                         /*  oder COMPARE-Anweisung beeinflusst          */
  448.                         destroys=0;
  449.                         if(as->z.flags&DREFOBJ) destroys|=1;
  450.                         if(as->code==CALL) destroys|=2;
  451.                         if(tp->q1.flags&VAR){
  452.                             if(destroys&3){
  453.                                 if((tp->q1.v->flags&USEDASADR)||
  454.                                    (tp->q1.flags&DREFOBJ)||
  455.                                    (tp->q1.v->storage_class==EXTERN)||
  456.                                    (tp->q1.v->nesting==0))
  457.                                     i=1;
  458.                                 if((destroys&2)&&tp->q1.v->storage_class==STATIC)
  459.                                     i=1;
  460.                             }
  461.                             if((as->z.flags&VAR)&&as->z.v==tp->q1.v)
  462.                                     i=1;
  463.                         }
  464.                         if(tp->q2.flags&VAR){
  465.                             if(destroys&3){
  466.                                 if((tp->q2.v->flags&USEDASADR)||
  467.                                    (tp->q2.flags&DREFOBJ)||
  468.                                    (tp->q2.v->storage_class==EXTERN)||
  469.                                    (tp->q2.v->nesting==0))
  470.                                     i=1;
  471.                                 if((destroys&2)&&tp->q2.v->storage_class==STATIC)
  472.                                     i=1;
  473.                             }
  474.                             if((as->z.flags&VAR)&&as->z.v==tp->q2.v)
  475.                                 i=1;
  476.                         }
  477.                         if(!i){
  478.                             if(DEBUG&1024){ printf("moving instruction from following blocks to predecessor:\n");pric2(stdout,as);}
  479.                             p=mymalloc(ICS);
  480.                             memcpy(p,as,ICS);
  481.                             remove_IC_fg(a,as);
  482.                             remove_IC_fg(b,bs);
  483.                             insert_IC_fg(g,g->end->prev->prev,p);
  484.                             changed=gchanged=1;
  485.                         }
  486.                     }
  487.                 }
  488.             }
  489.             g=g->normalout;
  490.         }
  491.         if(changed) free_flowgraph(fg);
  492.     }while(changed);
  493.     return(fg);
  494. }
  495.  
  496. void insert_IC_fg(struct flowgraph *fg,struct IC *p,struct IC *new)
  497. /*  fuegt ein IC hinter p ein unter Beibehaltung des Flussgraphen   */
  498. {
  499.     if(fg->start){
  500.         if(!p||p==fg->start->prev) fg->start=new;
  501.         if(p==fg->end) fg->end=new;
  502.     }else{
  503.         fg->start=fg->end=new;
  504.     }
  505.     insert_IC(p,new);
  506. }
  507.